package com.groupbuying.settleconsumer.service.impl;

import com.alibaba.fastjson.JSON;
import com.aliyun.openservices.ons.api.Producer;
import com.groupbuying.settleconsumer.connector.SysconfigFeign;
import com.groupbuying.settleconsumer.connector.YSFeign;
import com.groupbuying.settleconsumer.constants.SettleUshopYsSplitSyncreceiptEnumConstants;
import com.groupbuying.settleconsumer.constants.SettleYsSplitReceiptEnumConstants;
import com.groupbuying.settleconsumer.constants.SettleYsSplitRequestReceiptEnumConstants;
import com.groupbuying.settleconsumer.dao.SettleUshopYSSplitReceiptDao;
import com.groupbuying.settleconsumer.dao.SettleUshopYSSplitRequestReceiptDao;
import com.groupbuying.settleconsumer.dao.SettleUshopYsSplitSyncreceiptDao;
import com.groupbuying.settleconsumer.domain.SettleUshopYSSplitReceiptDO;
import com.groupbuying.settleconsumer.domain.SettleUshopYSSplitRequestReceiptDO;
import com.groupbuying.settleconsumer.domain.SettleUshopYsSplitSyncreceiptDO;
import com.groupbuying.settleconsumer.dto.YSDivListDTO;
import com.groupbuying.settleconsumer.dto.YSSplitReceiptDTO;
import com.groupbuying.settleconsumer.service.SettleUshopYSSplitReceiptService;
import com.groupbuying.settleconsumer.utils.DateUtils;
import com.groupbuying.settleconsumer.utils.JsonUtils;
import com.groupbuying.settleconsumer.utils.apiresult.ApiResult;
import com.groupbuying.settleconsumer.utils.apiresult.ApiResultCode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: WANGNING
 * @Email wyn20140226@aliyun.com
 * @Date: 2019/5/10 16:37
 * @Des 银盛分账异步回执业务处理
 */
@Service
public class SettleUshopYSSplitReceiptServiceImpl implements SettleUshopYSSplitReceiptService {
    public static final Logger logger = LoggerFactory.getLogger(SettleUshopYSSplitReceiptServiceImpl.class);
    @Autowired
    private SettleUshopYSSplitReceiptDao ysSplitReceiptDao;
    @Autowired
    private YSFeign ysFeign;
    @Autowired
    private SysconfigFeign sysconfigFeign;
    @Autowired
    private SettleUshopYsSplitSyncreceiptDao settleUshopYsSplitSyncreceiptDao;
    @Autowired
    private Producer producer;
    @Autowired
    private SettleUshopYSSplitRequestReceiptDao ysSplitRequestReceiptDao;
    @Override
    public SettleUshopYSSplitReceiptDO get(String id) {

        return this.ysSplitReceiptDao.get(id);
    }

    @Override
    public List<SettleUshopYSSplitReceiptDO> list(Map<String, Object> map) {

        return this.ysSplitReceiptDao.list(map);
    }

    @Override
    public int count(Map<String, Object> map) {

        return this.ysSplitReceiptDao.count(map);
    }
    /**银盛异步回执写入返回记录
     * @param splitReceipt
     * @return int
     */
    @Override
    public int save(SettleUshopYSSplitReceiptDO splitReceipt) {

        return this.ysSplitReceiptDao.save(splitReceipt);
    }

    @Override
    public int update(SettleUshopYSSplitReceiptDO splitReceipt) {

        return this.ysSplitReceiptDao.update(splitReceipt);
    }

    @Override
    public int remove(String id) {

        return this.ysSplitReceiptDao.remove(id);
    }

    @Override
    public int batchRemove(String[] ids) {

        return this.ysSplitReceiptDao.batchRemove(ids);
    }
    /**
     * 调用银盛分账
     * @param splitReceiptInfo
     * @return com.groupbuying.common.apiresult.ApiResult
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult createSplitReceipt(String splitReceiptInfo) {
        try {
            logger.info("SettleUshopYSSplitReceiptServiceImpl.createSplitReceipt()------监听到平台内部分账完成MQ，json为："+splitReceiptInfo);
            /*从mq消息消息*/
            Map<String, Object> mapParams = JsonUtils.jsonToMap(splitReceiptInfo);
            /*原订单号*/
            String outTradeNo = (String) mapParams.get("out_trade_no");
            /*原订单交易金额*/
            BigDecimal totalAmount = ((BigDecimal) mapParams.get("total_amount")).setScale(2, RoundingMode.HALF_UP);
            /*分账子商户号*/
            String divisionMerUsercode = (String) mapParams.get("division_mer_usercode");
            /*子商户分账金额*/
            BigDecimal divAmount = ((BigDecimal) mapParams.get("div_amount")).setScale(2, RoundingMode.HALF_UP);
            /*银盛平台积分账户号*/
            String virtualCode = this.sysconfigFeign.getYSgymarketing();
            /*积分金额*/
            BigDecimal virtualAmount = ((BigDecimal) mapParams.get("virtual_amount")).setScale(2, RoundingMode.HALF_UP);
            /*银盛平台开设平台号*/
           String planformCode = this.sysconfigFeign.getYSPlanformCode();
            /*银盛平台开设平台金额*/
            BigDecimal planformAmount =((BigDecimal) mapParams.get("planform_amount")).setScale(2, RoundingMode.HALF_UP);
            /*在银盛开设平台金额与积分金额总和--目前把积分放到平台账户上*/
           // BigDecimal planformAmounts= virtualAmount.add(planformAmount);
            /*主商户号（原交易收款方*/
            String payeeUsercode = this.sysconfigFeign.getPayeeUsercode();
            /*原订单是否参与分账01：是，02否*/
            String isDivistion = SettleYsSplitReceiptEnumConstants.ENUM_IS_DIVISTION;
            /*分账模式01 ：比例，02：金额*/
            String divisionMode = SettleYsSplitReceiptEnumConstants.ENUM_MODE_CASH;
            /*是否重新分账*/
            String isAgainDivision = SettleYsSplitReceiptEnumConstants.ENUM_DIVISIONAGAIN_YES;
            YSSplitReceiptDTO ysSplitReceiptDTO = new YSSplitReceiptDTO();
            /*分账商户*/
            YSDivListDTO merUserCodeDTO = new YSDivListDTO();
            merUserCodeDTO.setDivision_mer_usercode(divisionMerUsercode);
            merUserCodeDTO.setDiv_amount(divAmount);
            merUserCodeDTO.setIs_chargeFee(SettleYsSplitReceiptEnumConstants.ENUM_YSE_CHARGEFEE);
            /*银盛平台开设积分分账*/
            YSDivListDTO virtualDTO = new YSDivListDTO();
            virtualDTO.setDivision_mer_usercode(virtualCode);
            virtualDTO.setDiv_amount(virtualAmount);
            virtualDTO.setIs_chargeFee(SettleYsSplitReceiptEnumConstants.ENUM_NO_CHARGEFEE);
            /*银盛平台主商户分账*/
            YSDivListDTO planformDTO = new YSDivListDTO();
            planformDTO.setDivision_mer_usercode(planformCode);
            planformDTO.setDiv_amount(planformAmount);
            planformDTO.setIs_chargeFee(SettleYsSplitReceiptEnumConstants.ENUM_NO_CHARGEFEE);
            List<YSDivListDTO> divList = new ArrayList<YSDivListDTO>();
            /*判断商户分账*/
            //平台无抽成
            if(planformAmount.compareTo(BigDecimal.ZERO)==0.00){
                //平台无抽成，积分无抽成
                if(virtualAmount.compareTo(BigDecimal.ZERO)==0.00){
                    divList.add(merUserCodeDTO);
                }else{
                    //平台无抽成，积分有抽成
                    divList.add(merUserCodeDTO);
                    divList.add(virtualDTO);
                }
            }else{
                //平台有抽成，积分无抽成
                if(virtualAmount.compareTo(BigDecimal.ZERO)==0.00){
                    divList.add(merUserCodeDTO);
                    divList.add(planformDTO);
                }else{
                    //平台、积分都有抽成
                    divList.add(merUserCodeDTO);
                    divList.add(planformDTO);
                    divList.add(virtualDTO);
                }

            }
            /*divList.add(merUserCodeDTO);
            //divList.add(virtualDTO);
            divList.add(planformDTO);*/
            ysSplitReceiptDTO.setOut_trade_no(outTradeNo);
            ysSplitReceiptDTO.setPayee_usercode(payeeUsercode);
            ysSplitReceiptDTO.setDivision_mode(divisionMode);
            ysSplitReceiptDTO.setTotal_amount(totalAmount);
            ysSplitReceiptDTO.setIs_divistion(isDivistion);
            ysSplitReceiptDTO.setDiv_list(divList);
            ysSplitReceiptDTO.setIs_again_division(isAgainDivision);
            String ysSplitReceiptJSON = JsonUtils.objectToJson(ysSplitReceiptDTO);
            Map<String, Object> ysSplitReceiptMap = new ConcurrentHashMap<String, Object>();
            ysSplitReceiptMap.put("biz_content", ysSplitReceiptJSON);
            logger.info("SettleUshopYSSplitReceiptServiceImpl.createSplitReceipt()------拼接请求银盛数据格式：ysSplitReceiptJSON："+ysSplitReceiptJSON);
            /*同步返回数据写库*/
            SettleUshopYsSplitSyncreceiptDO settleUshopYsSplitSyncreceiptDO=new SettleUshopYsSplitSyncreceiptDO();
            settleUshopYsSplitSyncreceiptDO.setReturnCode(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_BEGIN_RETURNCODE);
            settleUshopYsSplitSyncreceiptDO.setRetrunInfo(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_BEGIN_RETRUNINFO);
            settleUshopYsSplitSyncreceiptDO.setGmtCreate(new Date());
            settleUshopYsSplitSyncreceiptDO.setGmtModified(new Date());
            settleUshopYsSplitSyncreceiptDO.setIsDelete(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_ISDELETE_UNDEL);
            settleUshopYsSplitSyncreceiptDO.setOutTradeNo(outTradeNo);
            settleUshopYsSplitSyncreceiptDO.setCode(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_INIT_CODE);
            settleUshopYsSplitSyncreceiptDO.setMsg(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_INIT_MSG);
            settleUshopYsSplitSyncreceiptDO.setNote(ysSplitReceiptJSON);
            settleUshopYsSplitSyncreceiptDO.setStatus(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_STATUS_FAIL);
            settleUshopYsSplitSyncreceiptDao.save(settleUshopYsSplitSyncreceiptDO);
            logger.info("SettleUshopYSSplitReceiptServiceImpl.createSplitReceipt()------初始化银盛同步返回数据表成功！！！");
            logger.info("SettleUshopYSSplitReceiptServiceImpl.createSplitReceipt()------调用银盛分账前请求参数biz_content："+ysSplitReceiptMap.get("biz_content"));
            /*请求银盛分账*/
            String splitReceiptStr = ysFeign.ysSplitReceipt(ysSplitReceiptMap);
            logger.info("SettleUshopYSSplitReceiptServiceImpl.createSplitReceipt()------调用银盛分账返回json："+splitReceiptStr);
                /*解析银盛分账同步返回参数json*/
                Map map=JsonUtils.jsonToMap(splitReceiptStr);
                String returnCode=(String)map.get("returnCode");
                if(returnCode.equalsIgnoreCase(SettleYsSplitReceiptEnumConstants.ENUM_RETURN_CODE)){
                    settleUshopYsSplitSyncreceiptDO.setReturnCode((String)map.get("returnCode"));
                    settleUshopYsSplitSyncreceiptDO.setRetrunInfo((String)map.get("retrunInfo"));
                    settleUshopYsSplitSyncreceiptDO.setStatus(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_STATUS_SUCCESS);
                    settleUshopYsSplitSyncreceiptDO.setMsg((String)map.get("msg"));
                    settleUshopYsSplitSyncreceiptDO.setCode((String)map.get("code"));
                    settleUshopYsSplitSyncreceiptDO.setOutTradeNo(outTradeNo);
                    settleUshopYsSplitSyncreceiptDO.setNote(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_END_NOTE);
                    settleUshopYsSplitSyncreceiptDO.setGmtModified(new Date());
                    settleUshopYsSplitSyncreceiptDao.update(settleUshopYsSplitSyncreceiptDO);
                    logger.info("SettleUshopYSSplitReceiptServiceImpl.createSplitReceipt()------银盛分账同步返回有值，返回成功!");
                    return ApiResult.success();
                }else{
                    //判断返回参数信息是否调用主动查询
                    Map<String,Object> params =new HashMap<String,Object>();
                    String outTradeNos=settleUshopYsSplitSyncreceiptDO.getOutTradeNo();
                    params.put("out_trade_no", outTradeNos);
                    SettleUshopYsSplitSyncreceiptDO settleUshopYsSplitSyncreceipt=settleUshopYsSplitSyncreceiptDao.getSettleUshopYsSplitSyncreceipt(params);
                    String status =settleUshopYsSplitSyncreceipt.getStatus();
                    //是否调用银盛分账--如果在本地未查询到状态成功需要调用银盛分账查询
                    if(status.equalsIgnoreCase(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_STATUS_FAIL)){
                        logger.info("SettleUshopYSSplitReceiptServiceImpl.createSplitReceipt()------第二次开始调用银盛分账请求，请求参数为MAP："+ysSplitReceiptMap);
                        //重新调用银盛分账
                        String splitReceiptJson= ysFeign.ysSplitReceipt(ysSplitReceiptMap);
                        logger.info("SettleUshopYSSplitReceiptServiceImpl.createSplitReceipt()------第二次开始调用银盛分账返回参数json："+splitReceiptJson);
                        Map repeatMap=JsonUtils.jsonToMap(splitReceiptJson);
                        String repeatReturnCode=(String)repeatMap.get("returnCode");
                        //重新调用成功
                        if(repeatReturnCode.equalsIgnoreCase(SettleYsSplitReceiptEnumConstants.ENUM_RETURN_CODE)){
                            //更改同步返回记录表记录
                            settleUshopYsSplitSyncreceiptDO.setMsg((String)map.get("msg"));
                            settleUshopYsSplitSyncreceiptDO.setCode((String)map.get("code"));
                            settleUshopYsSplitSyncreceiptDO.setReturnCode((String)map.get("returnCode"));
                            settleUshopYsSplitSyncreceiptDO.setRetrunInfo((String)map.get("retrunInfo"));
                            settleUshopYsSplitSyncreceiptDO.setStatus(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_STATUS_SUCCESS);
                            settleUshopYsSplitSyncreceiptDO.setGmtModified(new Date());
                            settleUshopYsSplitSyncreceiptDao.update(settleUshopYsSplitSyncreceiptDO);
                            logger.info("SettleUshopYSSplitReceiptServiceImpl.createSplitReceipt()------重新调用银盛分账接口成功，返回成功");
                            return ApiResult.success();
                        }else{
                            //直接调用分账查询返回异常
                            String ysRequestReceiptJson =ysSplitRequest(outTradeNo);
                            Map ysSplitRequestMap=JsonUtils.jsonToMap(ysRequestReceiptJson);
                            String msg=(String)ysSplitRequestMap.get("msg");
                            settleUshopYsSplitSyncreceiptDO.setMsg((String)ysSplitRequestMap.get("msg"));
                            settleUshopYsSplitSyncreceiptDO.setCode((String)ysSplitRequestMap.get("code"));
                            settleUshopYsSplitSyncreceiptDO.setReturnCode(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_YSREQUEST_RETURNCODE);
                            settleUshopYsSplitSyncreceiptDO.setRetrunInfo(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_YSREQUEST_RETRUNINFO);
                            settleUshopYsSplitSyncreceiptDO.setStatus(SettleUshopYsSplitSyncreceiptEnumConstants.ENUM_STATUS_FAIL);
                            settleUshopYsSplitSyncreceiptDao.update(settleUshopYsSplitSyncreceiptDO);
                            logger.info("SettleUshopYSSplitReceiptServiceImpl.createSplitReceipt()------调用银盛分账查询，直接返回信息,返回的信息为"+ysRequestReceiptJson);
                            return ApiResult.failure(ApiResultCode.FAILURE, msg);
                        }
                    }
                }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("SettleUshopYSSplitReceiptServiceImpl-->createSplitReceipt fail e:",e);
        }
        return ApiResult.failure(ApiResultCode.FAILURE);
    }
    //调用银盛分账查询
    private String ysSplitRequest(String outTradeNo) {
        Map<String ,Object> messageMap=new HashMap<>();
        messageMap.put("out_trade_no", outTradeNo);
        messageMap.put("src_usercode", sysconfigFeign.getPayeeUsercode());
        String requestReceiptJson= JsonUtils.toJSon(messageMap);
        Map<String,Object> condMap=new HashMap<>();
        condMap.put("biz_content", requestReceiptJson);
        logger.info("SettleUshopYSSplitReceiptServiceImpl.ysSplitRequest()------调用银盛分账查询前参数为："+condMap.get("biz_content"));
        //通过feign结构调用分账查询
        String ysRequestReceiptJson=this.ysFeign.splitRequestReceipt(messageMap);
        logger.info("SettleUshopYSSplitReceiptServiceImpl.ysSplitRequest()------调用银盛分账查询后json："+ysRequestReceiptJson);
        Map feignMap=JsonUtils.jsonToMap(ysRequestReceiptJson);
        SettleUshopYSSplitRequestReceiptDO ysSplitResquestReturn=new SettleUshopYSSplitRequestReceiptDO();
        ysSplitResquestReturn.setCode((String) feignMap.get("code"));
        ysSplitResquestReturn.setMsg((String) feignMap.get("msg"));
        ysSplitResquestReturn.setSrcUsercode((String) feignMap.get("src_usercode"));
        ysSplitResquestReturn.setTradeDate((String) feignMap.get("trade_date"));
        ysSplitResquestReturn.setOutTradeNo((String) feignMap.get("out_trade_no"));
        ysSplitResquestReturn.setOutBatchNo(DateUtils.format(new Date(), "yyyyMMdd"));
        ysSplitResquestReturn.setDivisionMode((String) feignMap.get("division_mode"));
        ysSplitResquestReturn.setTotalAmount(new BigDecimal((String)feignMap.get("total_amount")));
        ysSplitResquestReturn.setFee(new BigDecimal((String) feignMap.get("fee")));
        ysSplitResquestReturn.setFeePayer((String) feignMap.get("fee_payer"));
        ysSplitResquestReturn.setDivisionStatus((String) feignMap.get("division_status"));
        ysSplitResquestReturn.setDivisionStatusCode((String) feignMap.get("division_status_code"));
        ysSplitResquestReturn.setNote((String) feignMap.get("note"));
        List list=(List) feignMap.get("detailResults");
        String str= JSON.toJSON(list).toString();
        ysSplitResquestReturn.setDetailResults(str);
        ysSplitResquestReturn.setGmtCreate(new Date());
        ysSplitResquestReturn.setGmtModified(new Date());
        ysSplitResquestReturn.setIsDelete(SettleYsSplitRequestReceiptEnumConstants.ENUM_ISDELETE_UNDEL);
        ysSplitRequestReceiptDao.save(ysSplitResquestReturn);
        logger.info("SettleUshopYSSplitReceiptServiceImpl.ysSplitRequest()------调用银盛分账查询成功落库success，并且返回请求参数json："+ysRequestReceiptJson);
        return ysRequestReceiptJson;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult createAsynchronous(String splitReceiptStr) {
        /*银盛异步返回信息*/
        logger.info("SettleUshopYSSplitReceiptServiceImpl.createAsynchronous()------调用银盛分账异步回执参数为:"+splitReceiptStr);
        Map map=JsonUtils.jsonToMap(splitReceiptStr);
        String srcUserCode=(String)map.get("src_usercode");
        String outTradeNo=(String)map.get("out_trade_no");
        String divisionMode=(String)map.get("division_mode");
        String totalAmount=(String)map.get("total_amount");
        String fee=(String)map.get("fee");
        String feePayer=(String)map.get("fee_payer");
        String divisionStatus=(String)map.get("division_status");
        String divisionStatusCode=(String)map.get("division_status_code");
        String updateTime=(String)map.get("update_time");
        String node=(String)map.get("note");
        String detailResults=(String)map.get("detailResults");
        String notifyType=(String)map.get("notify_type");
        String notifyTime=(String)map.get("notify_time");
        String signType=(String)map.get("sign_type");
        if(StringUtils.isNotEmpty(srcUserCode)&&StringUtils.isNotEmpty(outTradeNo)&&
            StringUtils.isNotEmpty(divisionMode)&&StringUtils.isNotEmpty(divisionStatus)&&StringUtils.isNotEmpty(divisionStatusCode)&&StringUtils.isNotEmpty(detailResults) &&StringUtils.isNotEmpty(signType)){
            try {
                //写入数据库
                SettleUshopYSSplitReceiptDO ysSplitReceiptDO=new SettleUshopYSSplitReceiptDO();
                ysSplitReceiptDO.setTradeDate(DateUtils.format(new Date(), "yyyyMMdd"));
                ysSplitReceiptDO.setSrcUsercode(srcUserCode);
                ysSplitReceiptDO.setOutTradeNo(outTradeNo);
                ysSplitReceiptDO.setOutBatchNo(DateUtils.format(new Date(), "yyyyMMdd"));
                ysSplitReceiptDO.setDivisionMode(divisionMode);
                ysSplitReceiptDO.setTotalAmount(new BigDecimal(totalAmount));
                ysSplitReceiptDO.setFee(new BigDecimal(fee));
                ysSplitReceiptDO.setFeePayer(feePayer);
                ysSplitReceiptDO.setDivisionStatus(divisionStatus);
                ysSplitReceiptDO.setDivisionStatusCode(divisionStatusCode);
                ysSplitReceiptDO.setNote(node);
                ysSplitReceiptDO.setDetailResults(detailResults);
                ysSplitReceiptDO.setGmtCreate(new Date());
                ysSplitReceiptDO.setGmtModified(new Date());
                ysSplitReceiptDO.setIsDelete(SettleYsSplitReceiptEnumConstants.ENUM_ISDELETE_UNDEL);
                ysSplitReceiptDO.setNotifyType(notifyType);
                ysSplitReceiptDO.setNotifyTime(notifyTime);
                ysSplitReceiptDO.setSign(SettleYsSplitReceiptEnumConstants.ENUM_SIGN_SUCCESS);
                ysSplitReceiptDO.setSignType(signType);
                int res=this.save(ysSplitReceiptDO);
                if(res>0){
                    logger.info("SettleUshopYSSplitReceiptServiceImpl.createAsynchronous()------调用银盛分账异步回执参数写入成功success！！！");
                    return ApiResult.success();
                }else{
                    logger.info("SettleUshopYSSplitReceiptServiceImpl.createAsynchronous()------调用银盛分账异步回执参数写入失败！！！");
                    return ApiResult.failure(ApiResultCode.FAILURE);
                }

            } catch (Exception e) {
                e.printStackTrace();
                logger.error("SettleUshopYSSplitReceiptServiceImpl.createAsynchronous()------调用银盛分账异步回执参数写入异常！！！",e);
            }
        }
        return ApiResult.failure(ApiResultCode.FAILURE);
    }
}
